預設情況下,容器內的檔案系統是短暫的 (Ephemeral)。當容器崩潰並被 kubelet
重啟時,所有檔案都會遺失。此外,在一個擁有多个容器的 Pod 中,容器之間也無法直接共享檔案。
為了解決這些問題,Kubernetes 引入了 Volume (儲存卷) 的概念。Volume 是一個可以被掛載到 Pod 中一個或多個容器的目錄,它的生命週期獨立於容器。
K8s 的 Volume 抽象模型非常強大,它支援多種類型,可以滿足各種不同的儲存需求。我們可以將其大致分為兩大類:
本篇文章將聚焦於幾種最常用的非持久性 Volume。
在 K8s 中,使用 Volume 分為兩步:
.spec.volumes
中定義一個 Volume,並給它一個名字。.spec.containers.volumeMounts
中,透過名字引用上面定義的 Volume,並指定要將它掛載到容器內的哪個路徑 (mountPath
)。graph TD
subgraph Pod Spec
direction LR
A["`.spec.volumes` <br> (定義 Volume)"]
B["`.spec.containers.volumeMounts` <br> (掛載 Volume)"]
end
A -- "透過 name 引用" --> B
Volume 類型 | 核心用途 | 範例 |
---|---|---|
emptyDir |
Pod 內容器之間的臨時共享空間。 | 一個容器寫入資料,另一個 Sidecar 容器讀取並處理。 |
configMap |
將 ConfigMap 物件的內容以檔案形式掛載到容器中。 | 將 nginx.conf 設定檔注入到 NGINX 容器中。 |
secret |
將 Secret 物件的內容以檔案形式掛載到容器中。 | 將 TLS 憑證和私鑰掛載到 Ingress Controller 中。 |
hostPath |
將節點 (Node) 的檔案系統上的檔案或目錄掛載到容器中。 | 日誌收集代理 (DaemonSet) 需要讀取節點上的 /var/log 目錄。 |
downwardAPI |
將 Pod 自身的元數據 (如名稱、標籤、註解) 以檔案形式暴露給容器內部。 | 應用程式需要知道自己正在哪個 Namespace 或哪個 Node 上運行。 |
emptyDir
範例一個 emptyDir
Volume 在 Pod 被分配到節點時首次建立,只要該 Pod 在該節點上運行,該 Volume 就會一直存在。當 Pod 因任何原因從節點上移除時,emptyDir
中的資料將被永久刪除。
configMap
/ secret
範例這是將設定與應用程式分離的最佳實踐。
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox:1.28
command: ['sh', '-c', 'cat /etc/config/log_level']
volumeMounts:
- name: config-volume # 引用下面定義的 Volume
mountPath: /etc/config # 掛載到容器的路徑
volumes:
- name: config-volume # 定義一個名為 config-volume 的 Volume
configMap:
name: log-config # 指定來源是名為 log-config 的 ConfigMap
items:
- key: log_level # 指定要掛載的 key
path: log_level.conf # 掛載後的檔名
hostPath
的注意事項hostPath
是一個強大但危險的功能,它打破了容器的隔離性。
hostPath
。以上介紹的 Volume 類型,其生命週期都與 Pod 綁定。當我們需要處理像資料庫這樣、資料必須在 Pod 重啟甚至刪除後依然存在的場景時,就需要進入持久化儲存 (Persistent Storage) 的世界了。
在下一篇文章中,我們將深入探討 K8s 如何透過 PersistentVolume
(PV)、PersistentVolumeClaim
(PVC) 和 StorageClass
(SC) 這一套精巧的機制,來實現與儲存後端的解耦和動態配置。